<template>
  <div class="components-chart-box">
    <h4 v-if="props.title" class="chart-title" ref="titleRef">{{ props.title }}</h4>
    <div
:class="[chartClass, 'chart-container', props.bordered && 'bordered']" v-loading="loading" ref="chartRef"
      :style="{ height, width }">
    </div>
  </div>
</template>
<script lang="ts" setup>
import { onMounted, PropType, Ref, ref, watch, onUnmounted } from 'vue'
import { useECharts } from '@/hooks/web/useECharts'
import { EChartsOption } from 'echarts'
import { getCssVariableValue, getRandomColor } from '../common'
import { colorArr } from './data'
import { XData, YData } from '@/api/common/model/chart'
import '../style.scss'
import { XAXisOption } from 'echarts/types/dist/shared'

const props = defineProps({
  width: {
    type: String as PropType<string>,
    default: '100%',
  },
  height: {
    type: String as PropType<string>,
    default: '100%',
  },
  loading: {
    type: Boolean,
    default: false,
  },
  bordered: {
    type: Boolean,
    default: true,
  },
  title: {
    type: String as PropType<string>,
    default: '',
  },
  chartData: {
    type: Object as PropType<object>,
  },
  chartClass: {
    type: Object as PropType<string>,
  },
  unit: {
    type: String as PropType<string>,
    default: '',
  },
  xyDataFieldsName: {
    type: Object,
    default: () => ({
      xDataField: 'xaxisList',
      yDataField: 'yaxisList',
    }),
  },
  stack: {
    type: String,
    default: undefined,
  },
})

let resizeObserver: ResizeObserver | null = null

const chartRef = ref<HTMLDivElement | null>(null)
const titleRef = ref<HTMLDivElement | null>(null)
const { setOptions, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>)
const gridLineColor = getCssVariableValue('--chart-grid-line-color')
const textColor = getCssVariableValue('--chart-text-color')

const returnTooltipDom = (data: any) => {
  let result = '<ul class="legend-list-bar">'
  for (let item of data) {
    const { seriesName, value, color } = item
    result += `<li>
                    <span class="rect" style="background: ${color}"></span>
                    <span >${seriesName}：</span>${value}
                  </li>`
  }
  result += '</ul>'
  return result
}
// 标题高度 + 上间距 + 标题距离 grid 间距
const gridTop = 14 + 12 + 12
const gridBottom = 14 + 16
const options: EChartsOption = {
  backgroundColor: '#fff',
  legend: {
    right: 16,
    padding: 0,
    top: 10,
    textStyle: {
      color: textColor,
    },
    icon: 'rect',
    itemWidth: 10,
    itemHeight: 10,
  },
  grid: {
    left: '12px',
    right: '12px',
    bottom: '12px',
    top: gridTop,
    containLabel: true,
  },
  tooltip: {
    trigger: 'axis',
    appendToBody: true,
    className: 'echarts-line-tooltip',
    axisPointer: {
      type: 'shadow',
      label: {
        show: true,
        backgroundColor: '#333',
      },
    },
    formatter: function (params: any) {
      return returnTooltipDom(params)
    },
  },
  xAxis: {
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  },
  yAxis: {
    nameTextStyle: {
      color: textColor,
      fontSize: '12px',
    },
    splitLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLine: {
      lineStyle: {
        color: gridLineColor,
      },
    },
    axisLabel: {
      color: textColor,
    },
  },
}

onMounted(() => {
  setData()
  resizeObserver = new ResizeObserver(() => {
    resize()
  })
  if (chartRef.value) {
    resizeObserver.observe(chartRef.value as HTMLDivElement)
  }
})

onUnmounted(() => {
  if (resizeObserver && chartRef.value) {
    resizeObserver.unobserve(chartRef.value as HTMLDivElement)
  }
})

const renderTable = (chartInstance, tableConfig) => {
  if (!tableConfig.show) return;

  // 先清除之前可能存在的表格
  const existingTable = chartInstance.getDom().querySelector('.echarts-table');
  if (existingTable) {
    existingTable.remove();
  }

  const tableDom = document.createElement('div');
  tableDom.className = 'echarts-table';
  tableDom.style.position = 'absolute';
  tableDom.style.bottom = tableConfig.bottom;
  tableDom.style.left = tableConfig.left;
  tableDom.style.width = tableConfig.width;
  tableDom.style.height = '50px';

  const table = document.createElement('table');
  table.style.borderCollapse = 'collapse';
  table.style.width = '100%';
  table.style.height = '100%';
  table.style.textAlign = 'center';
  table.style.border = '1px solid #ddd';

  // 第一行：显示 X 轴数据
  // const tr1 = document.createElement('tr');
  const thFirst = document.createElement('th');
  thFirst.innerText = '';  // 第一列留空
  Object.assign(thFirst.style, {
    ...tableConfig.header,
    border: '1px solid #ddd',
    width: '80px',
    height: '10px'
  });
  // tr1.appendChild(thFirst);

  if (tableConfig.xaxisList) {
    tableConfig.xaxisList.forEach(value => {
      const th = document.createElement('th');
      th.innerText = value;
      Object.assign(th.style, {
        ...tableConfig.header,
        border: '1px solid #ddd',
        paddingLeft: '10px',
        height: '10px'
      });
      // tr1.appendChild(th);
    });
  }
  // table.appendChild(tr1);

  // 第二行：本周数据
  const tr2 = document.createElement('tr');
  const thWeek = document.createElement('th');
  thWeek.innerText = '本周';
  Object.assign(thWeek.style, {
    ...tableConfig.header,
    fontSize: '12px',
    whiteSpace: 'nowrap',
    border: '1px solid #ddd',
    width: '80px',
    height: '10px'  // 调整第二行高度
  });
  tr2.appendChild(thWeek);

  if (tableConfig.data[0]) {
    tableConfig.data[0].forEach(value => {
      const td = document.createElement('td');
      td.innerText = value !== undefined ? value : '-';
      Object.assign(td.style, {
        ...tableConfig.cellStyle,
        border: '1px solid #ddd',
        paddingLeft: '10px',
        height: '10px'  // 调整第二行高度
      });
      tr2.appendChild(td);
    });
  }
  table.appendChild(tr2);

  // 第三行：上周数据
  const tr3 = document.createElement('tr');
  const thLastWeek = document.createElement('th');
  thLastWeek.innerText = '上周';
  Object.assign(thLastWeek.style, {
    ...tableConfig.header,
    fontSize: '12px',
    whiteSpace: 'nowrap',
    border: '1px solid #ddd',
    width: '80px',
    height: '10px'  // 调整第三行高度
  });
  tr3.appendChild(thLastWeek);

  if (tableConfig.data[1]) {
    tableConfig.data[1].forEach(value => {
      const td = document.createElement('td');
      td.innerText = value !== undefined ? value : '-';
      Object.assign(td.style, {
        ...tableConfig.cellStyle,
        border: '1px solid #ddd',
        paddingLeft: '10px',
        height: '10px'  // 调整第三行高度
      });
      tr3.appendChild(td);
    });
  }
  table.appendChild(tr3);

  tableDom.appendChild(table);
  chartInstance.getDom().appendChild(tableDom);
}

const setData = () => {
  const { xDataField, yDataField } = props.xyDataFieldsName
  if (!props.chartData || !chartRef.value) return
  const chartTitleW = titleRef.value ? titleRef.value.offsetWidth : 0
  const legendWidth = chartRef.value?.clientWidth - chartTitleW - 36
  const xData = props.chartData[xDataField] as XData
  const yData = props.chartData[yDataField] as YData[]
  if (!xData || !yData) return
  const showUnit = yData.length && props.unit

  // 调用 renderTable 函数
  if ('table' in props.chartData && props.chartData.table) {
    const chartInstance = getInstance()
    if (chartInstance) {
      renderTable(chartInstance, props.chartData.table)
    }
  }

  setOptions({
    ...options,
    legend: {
      ...options.legend,
      width: legendWidth,
      data: yData.map((item) => item.name),
      type: 'scroll',
    },
    grid: {
      ...options.grid,
      top: showUnit ? gridTop + 14 : gridTop,
      bottom: 'table' in props.chartData ? gridBottom + 30 : gridBottom
    },
    xAxis: {
      ...options.xAxis,
      data: xData,
    } as XAXisOption,
    yAxis: {
      ...options.yAxis,
      name: showUnit && props.unit ? `单位：${props.unit}` : undefined,
    },
    series: yData.map((item, index) => {
      const color = colorArr[index] || getRandomColor()
      return {
        ...item,
        type: 'bar',
        stack: props.stack,
        itemStyle: {
          color,
        },
        barMaxWidth: 28,
      }
    }),
    backgroundColor: '#fff'
  })
}

watch(
  () => props.chartData,
  (val) => {
    setData()
  },
  {
    immediate: true,
  },
)

defineExpose({
  getInstance
})
</script>
<style scoped lang="scss"></style>
<style lang="scss">
.echarts-line-tooltip {
  .legend-list-bar {
    li {
      display: flex;
      align-items: center;
      color: #666;
      font-size: 12px;
      line-height: 24px;

      &:not(:last-child) {
        margin-bottom: 4px;
      }

      .rect {
        display: block;
        width: 12px;
        height: 12px;
        margin-right: 3px;
      }
    }
  }
}
</style>
